package com.ddm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ddm.entity.*;
import com.ddm.mapper.Level1Mapper;
import com.ddm.mapper.Level2Mapper;
import com.ddm.mapper.Level3Mapper;
import com.ddm.mapper.Level4Mapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 丁丁猫
 * @version 1.0
 */
@Service
@RequiredArgsConstructor
public class IndicatorService {
    @Autowired
    private Level1Mapper level1Mapper;
    @Autowired
    private Level2Mapper level2Mapper;
    @Autowired
    private Level3Mapper level3Mapper;
    @Autowired
    private Level4Mapper level4Mapper;

    @Transactional(rollbackFor = Exception.class)
    public void deleteIndicator(String numId, Integer level, Long standardId) {
        // 参数校验
        if (numId == null || level < 1 || level > 4 || standardId == null) {
            throw new IllegalArgumentException("参数错误");
        }

        String[] parts = numId.split("\\.");
        if (parts.length < level) {
            throw new IllegalArgumentException("numId与level不匹配");
        }

        // 获取父级numId和删除位置
        String parentNumId = getParentNumId(parts, level);
        int deletePosition = Integer.parseInt(parts[level - 1]);

        // 删除当前条目及其子级
        deleteCurrentAndSubordinates(numId, level, standardId);

        // 查找并调整后续同级条目
        adjustSiblingIndicators(parentNumId, level, standardId, deletePosition);

        //更新父项目If_next_level
        if (numIdEndsWithOne(numId)) {
            updateParentIfLevel(numId, level, standardId, parentNumId);
        }
    }

    private void updateParentIfLevel(String numId, Integer level, Long standardId, String parentNumId) {
        if (level == 1) return;
        LambdaQueryWrapper<Level2> level2 = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<Level3> level3 = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<Level4> level4 = new LambdaQueryWrapper<>();
        switch (level) {
            case 2:
                level2.eq(Level2::getNumId, numId).eq(Level2::getStandardId, standardId);
                Integer num1 = level2Mapper.selectCount(level2);
                if (num1 == 0)
                    level1Mapper.updateIfNextLevel(parentNumId, standardId, 0);
                break;
            case 3:
                level3.eq(Level3::getNumId, numId).eq(Level3::getStandardId, standardId);
                Integer num2 = level3Mapper.selectCount(level3);
                if (num2 == 0)
                    level2Mapper.updateIfNextLevel(parentNumId, standardId, 0);
                break;
            case 4:
                level4.eq(Level4::getNumId, numId).eq(Level4::getStandardId, standardId);
                Integer num3 = level4Mapper.selectCount(level4);
                if (num3 == 0)
                    level3Mapper.updateIfNextLevel(parentNumId, standardId, 0);
                break;
        }
    }
    private boolean numIdEndsWithOne(String numId) {
        String[] parts = numId.split("\\.");
        return parts.length > 0 && "1".equals(parts[parts.length - 1]);
    }
    private String getParentNumId(String[] parts, int level) {
        if (level == 1) {
            return "";
        }
        return String.join(".", Arrays.copyOf(parts, level - 1));
    }

    private void deleteCurrentAndSubordinates(String numId, int level, Long standardId) {
        // 删除当前条目
        deleteCurrentLevel(level, standardId, numId);

        // 删除子级条目
        for (int l = level + 1; l <= 4; l++) {
            deleteSubordinates(l, standardId, numId);
        }
    }

    private void deleteCurrentLevel(int level, Long standardId, String numId) {
        switch (level) {
            case 1:
                level1Mapper.delete(new QueryWrapper<Level1>()
                        .eq("standard_id", standardId)
                        .eq("num_id", numId));
                break;
            case 2:
                level2Mapper.delete(new QueryWrapper<Level2>()
                        .eq("standard_id", standardId)
                        .eq("num_id", numId));
                break;
            case 3:
                level3Mapper.delete(new QueryWrapper<Level3>()
                        .eq("standard_id", standardId)
                        .eq("num_id", numId));
                break;
            case 4:
                level4Mapper.delete(new QueryWrapper<Level4>()
                        .eq("standard_id", standardId)
                        .eq("num_id", numId));
                break;
            default:
                throw new IllegalArgumentException("Invalid level");
        }
    }

    private void deleteSubordinates(int subordinateLevel, Long standardId, String parentNumId) {
        String pattern = parentNumId + ".";
        switch (subordinateLevel) {
            case 2:
                level2Mapper.delete(new QueryWrapper<Level2>()
                        .eq("standard_id", standardId)
                        .likeRight("num_id", pattern));
                break;
            case 3:
                level3Mapper.delete(new QueryWrapper<Level3>()
                        .eq("standard_id", standardId)
                        .likeRight("num_id", pattern));
                break;
            case 4:
                level4Mapper.delete(new QueryWrapper<Level4>()
                        .eq("standard_id", standardId)
                        .likeRight("num_id", pattern));
                break;
            default:
                throw new IllegalArgumentException("Invalid subordinate level");
        }
    }

    private void adjustSiblingIndicators(String parentNumId, int level, Long standardId, int deletePosition) {
        List<? extends BaseLevel> siblings = findSiblings(parentNumId, level, standardId, deletePosition);

        for (BaseLevel sibling : siblings) {
            String oldNumId = sibling.getNumId();
            String newNumId = calculateNewNumId(oldNumId, level, deletePosition);

            // 更新当前条目numId
            updateLevelNumId(level, sibling, newNumId);

            // 更新所有子级numId前缀
            updateSubordinatesPrefix(oldNumId, newNumId, level, standardId);
        }
    }

    private List<? extends BaseLevel> findSiblings(String parentNumId, int level, Long standardId, int deletePosition) {
        if (level == 1) {
            // 对于一级指标，直接在 SQL 中过滤
            return level1Mapper.selectList(new QueryWrapper<Level1>()
                    .eq("standard_id", standardId)
                    .eq("level", level)
                    .apply("CAST(num_id AS UNSIGNED) > {0}", deletePosition));
        } else {
            String parentPattern = parentNumId + ".";
            List<? extends BaseLevel> allSiblings = getLevelEntities(level, standardId, parentPattern);
            // 过滤出序号大于删除位置的同级指标
            return allSiblings.stream().filter(entity -> {
                String[] parts = entity.getNumId().split("\\.");
                int pos = Integer.parseInt(parts[level - 1]);
                return pos > deletePosition;
            }).collect(Collectors.toList());
        }
    }


    private List<? extends BaseLevel> getLevelEntities(int level, Long standardId, String parentPattern) {
        switch (level) {
            case 2:
                return level2Mapper.selectList(new QueryWrapper<Level2>()
                        .eq("standard_id", standardId)
                        .eq("level", level)
                        .likeRight("num_id", parentPattern));
            case 3:
                return level3Mapper.selectList(new QueryWrapper<Level3>()
                        .eq("standard_id", standardId)
                        .eq("level", level)
                        .likeRight("num_id", parentPattern));
            case 4:
                return level4Mapper.selectList(new QueryWrapper<Level4>()
                        .eq("standard_id", standardId)
                        .eq("level", level)
                        .likeRight("num_id", parentPattern));
            default:
                throw new IllegalArgumentException("Invalid level");
        }
    }

    private String calculateNewNumId(String oldNumId, int level, int deletePosition) {
        String[] parts = oldNumId.split("\\.");
        int currentPosition = Integer.parseInt(parts[level - 1]);
        parts[level - 1] = String.valueOf(currentPosition - 1);
        return String.join(".", parts);
    }

    private void updateLevelNumId(int level, BaseLevel entity, String newNumId) {
        switch (level) {
            case 1:
                ((Level1) entity).setNumId(newNumId);
                level1Mapper.updateById((Level1) entity);
                break;
            case 2:
                ((Level2) entity).setNumId(newNumId);
                level2Mapper.updateById((Level2) entity);
                break;
            case 3:
                ((Level3) entity).setNumId(newNumId);
                level3Mapper.updateById((Level3) entity);
                break;
            case 4:
                ((Level4) entity).setNumId(newNumId);
                level4Mapper.updateById((Level4) entity);
                break;
        }
    }

    private void updateSubordinatesPrefix(String oldNumId, String newNumId, int level, Long standardId) {
        String oldPrefix = oldNumId + ".";
        String newPrefix = newNumId + ".";

        for (int l = level + 1; l <= 4; l++) {
            updateLevelSubordinates(l, standardId, oldPrefix, newPrefix);
        }
    }

    private void updateLevelSubordinates(int level, Long standardId, String oldPrefix, String newPrefix) {
        switch (level) {
            case 2:
                level2Mapper.updateNumIdPrefix(oldPrefix, newPrefix, standardId);
                break;
            case 3:
                level3Mapper.updateNumIdPrefix(oldPrefix, newPrefix, standardId);
                break;
            case 4:
                level4Mapper.updateNumIdPrefix(oldPrefix, newPrefix, standardId);
                break;
        }
    }
}